#include "stdafx.h"
#include "recordset.h"


CRecordSet::CRecordSet(sqlite3_stmt *pStmt3)
{

	std::map<unsigned int, std::string> mRecord;
	if(pStmt3 != NULL) {
		m_nFieldCount = sqlite3_column_count(pStmt3); 
		for (unsigned int i = 0; i < m_nFieldCount; ++i) {
			int nColumnType = sqlite3_column_type(pStmt3, i);
			std::string strColumnName = sqlite3_column_name(pStmt3, i);
			m_vFieldIndex[strColumnName] = i;
		}
	}

	while (sqlite3_step(pStmt3) == SQLITE_ROW)
	{
		UINT uloop = 1;
		for (uloop = 1; uloop <= m_nFieldCount; uloop++)
		{
			char *pszValue = (char *)sqlite3_column_text(pStmt3, uloop - 1);
			mRecord[uloop] = pszValue;
		}
		m_vRecordList.push_back(mRecord);
	}


	m_nRowCount = m_vRecordList.size();
	m_nFieldCount = m_vFieldIndex.size();
	m_nRowPosition = 0;

	m_Record = m_vRecordList[0];
}

CRecordSet::~CRecordSet(void)
{

}

std_method_type_impl(UINT) CRecordSet::Next()
{

	if (m_nRowPosition == m_nRowCount) {
		m_nRowPosition++;
		return S_ERROR;
	} else if (m_nRowPosition < m_nRowCount + 1) {
		try{
			m_Record = m_vRecordList[m_nRowPosition];
			m_nRowPosition++;
			return S_SUCCESS;
		}
		catch(...){
			return S_ERROR;
		}
	}	

	return S_ERROR;
}

std_method_type_impl(UINT) CRecordSet::Previous()
{

	if (m_nRowPosition <= 0) {
		return S_ERROR;
	} 
	m_nRowPosition--;
	try{
		m_Record = m_vRecordList[m_nRowPosition];
		return S_SUCCESS;
	}
	catch(...){
		return S_ERROR;
	}
}

std_method_type_impl(UINT) CRecordSet::First()
{
	m_nRowPosition = 0;
	try{
		m_Record = m_vRecordList[m_nRowPosition];
		return S_SUCCESS;
	}
	catch(...){
		return S_ERROR;
	}
}

std_method_type_impl(UINT) CRecordSet::Last()
{
	try{
		m_nRowPosition = m_nRowCount;
		m_Record = m_vRecordList[m_nRowPosition - 1];
		return S_SUCCESS;
	}
	catch(...){
		return S_ERROR;
	}
}

unsigned int CRecordSet::GetFieldIndex(LPCSTR lpszName)
{
	std::map<std::string, unsigned int>::iterator it = m_vFieldIndex.find(lpszName);
	if(it != m_vFieldIndex.end()) {
		return it->second + 1;
	}
	return 0;
}

std_method_impl CRecordSet::GetInt(LPCSTR lpszName, INT& nValue)
{
	unsigned int nIndex = GetFieldIndex(lpszName);
	return GetInt(nIndex, nValue);
}

std_method_impl CRecordSet::GetInt64(LPCSTR lpszName, int64& nValue)
{
	unsigned int nIndex = GetFieldIndex(lpszName);
	return GetInt64(nIndex, nValue);
}

std_method_impl CRecordSet::GetUInt(LPCSTR lpszName, UINT& nValue)
{
	unsigned int nIndex = GetFieldIndex(lpszName);
	return GetUInt(nIndex, nValue);
}

std_method_impl CRecordSet::GetUInt64(LPCSTR lpszName, uint64& nValue)
{
	unsigned int nIndex = GetFieldIndex(lpszName);
	return GetUInt64(nIndex, nValue);
}

std_method_impl CRecordSet::GetFloat(LPCSTR lpszName, float& fValue)
{
	unsigned int nIndex = GetFieldIndex(lpszName);
	return GetFloat(nIndex, fValue);
}

std_method_impl CRecordSet::GetDouble(LPCSTR lpszName, double& dValue)
{
	unsigned int nIndex = GetFieldIndex(lpszName);
	return GetDouble(nIndex, dValue);
}

std_method_type_impl(LPCSTR) CRecordSet::GetString(LPCSTR lpszName)
{
	unsigned int nIndex = GetFieldIndex(lpszName);
	return GetString(nIndex);
}

std_method_type_impl(const unsigned char*) CRecordSet::GetBlob(LPCSTR lpszName)
{
	unsigned int nIndex = GetFieldIndex(lpszName);
	return GetBlob(nIndex);
}

std_method_impl CRecordSet::GetInt(unsigned int nIndex, INT& nValue)
{
	if (nIndex <= 0 || nIndex > m_nFieldCount) {
		return S_FALSE;
	}
	nValue = atoi(m_Record[nIndex].c_str());
	return S_OK;
}

std_method_impl CRecordSet::GetInt64(unsigned int nIndex, int64& nValue)
{
	if (nIndex <= 0 || nIndex > m_nFieldCount) {
		return S_FALSE;
	}

	//nValue = _strtoi64(m_Record[nIndex].c_str(), NULL, 10);

	return S_OK;
}

std_method_impl CRecordSet::GetUInt(unsigned int nIndex, UINT& nValue)
{
	if (nIndex <= 0 || nIndex > m_nFieldCount) {
		return S_FALSE;
	}
	uint64 iValue;

	GetUInt64(nIndex, iValue);
	nValue = static_cast<UINT>(iValue);
	return S_OK;
}

std_method_impl CRecordSet::GetUInt64(unsigned int nIndex, uint64& nValue)
{ 
	if (nIndex <= 0 || nIndex > m_nFieldCount) {
		return S_FALSE;
	}

	//nValue = _strtoi64(m_Record[nIndex].c_str(), NULL, 10);

	return S_OK;
}

std_method_impl CRecordSet::GetFloat(unsigned int nIndex, float& fValue)
{
	if (nIndex <= 0 || nIndex > m_nFieldCount) {
		return S_FALSE;
	}
	fValue = static_cast<float>(strtod(m_Record[nIndex].c_str(), NULL));
	return S_OK;
}

std_method_impl CRecordSet::GetDouble(unsigned int nIndex, double& dValue)
{ 
	if (nIndex <= 0 || nIndex > m_nFieldCount) {
		return S_FALSE;
	}

	dValue = ::strtod(m_Record[nIndex].c_str(), NULL);

	return S_OK;
}


std_method_type_impl(LPCSTR) CRecordSet::GetString(unsigned int nIndex)
{
	if (nIndex <= 0 || nIndex > m_nFieldCount) {
		return NULL;
	}
	return m_Record[nIndex].c_str();
}

std_method_type_impl(const unsigned char*) CRecordSet::GetBlob(unsigned int nIndex)
{ 
	return (const unsigned char*)m_Record[nIndex].c_str();
}
 
HRESULT CRecordSet::CreateInstance(sqlite3_stmt* pStmt, IRecordSet** ppRecordSet)
{
	CRecordSet* p = ALLOC_NEW CRecordSet(pStmt);
	rc_assert(p != NULL, E_FAIL)
	return p->QueryInterface(IID_IRecordSet, (void **)ppRecordSet);
}


